import KDBush from 'kdbush'

export interface PointIndexOptions<T> {
  data: T[]
  getX: (t: T) => number
  getY: (t: T) => number
}

export class PointIndex<T> {
  private idx: KDBush
  private data: T[]

  constructor({ data, getX, getY }: PointIndexOptions<T>) {
    this.data = data
    const idx = new KDBush(data.length)
    for (const e of data) {
      idx.add(getX(e), getY(e))
    }
    idx.finish()
    this.idx = idx
  }

  public search(x: number, y: number, radius: number): T[] {
    return this.idx.within(x, y, radius).map((it) => this.data[it])
  }
}
